package com.sunday.common.netty.e4_TCP.server;

import io.netty.channel.*;
import io.netty.util.concurrent.EventExecutor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 都是 Netty 中处理入站数据的处理器，但在使用方式和功能上有一些区别：
 * <p>
 * SimpleChannelInboundHandler:
 * <p>
 * SimpleChannelInboundHandler 是一个特殊类型的 ChannelInboundHandler，用于处理入站消息并且自动释放消息对象。
 * 当消息被传递给 channelRead0 方法时，SimpleChannelInboundHandler 会负责自动释放处理完的消息对象，这减轻了用户的负担，因为不再需要手动释放消息。
 * <p>
 * ChannelInboundHandlerAdapter:
 * <p>
 * ChannelInboundHandlerAdapter 是 ChannelInboundHandler 接口的实现，提供了一组空方法的默认实现，使得用户可以只重写所需的方法而不必实现所有的方法。
 * 当使用 ChannelInboundHandlerAdapter 时，开发者需要手动管理消息对象的引用计数和释放，因为它并没有像 SimpleChannelInboundHandler 那样提供自动释放消息对象的功能。
 * 因此，SimpleChannelInboundHandler 更加方便，因为它将消息对象的释放工作封装在内部，而 ChannelInboundHandlerAdapter 则更为灵活，适合对消息处理过程有更高度控制需求的场景。
 * <p>
 * {@link ChannelInboundHandlerAdapter}
 * {@link ChannelHandlerMask.Skip}
 * {@link ChannelHandlerMask#mask(Class)}
 * {@link AbstractChannelHandlerContext#skipContext(AbstractChannelHandlerContext, EventExecutor, int, int)}
 * {@link DefaultChannelPipeline}
 * io.netty.channel.ChannelHandlerMask.Skip 是 Netty 框架中的枚举类型，用于标识在 ChannelPipeline 中跳过特定的 ChannelHandler。
 * 这个枚举类型通常用于指示某些处理器（ChannelHandler）在执行时需要被跳过。
 * <p>
 * 具体来说，该枚举类型通常用于 channelHandlerAdded 和 handlerRemoved 等方法，来表明一些特定的处理器不应该参与到后续的事件处理中。
 * Netty 在处理事件时会根据 ChannelHandler 的类型和 ChannelHandlerMask 进行相应的处理，以确保事件传播时的正确顺序和条件。
 */
@Slf4j
public class TcpServerHandler extends SimpleChannelInboundHandler<String> {

    static AtomicInteger count = new AtomicInteger(0);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        log.info("[Server]channelRead0 -> Channel 读取数据时触发");
        log.info("[Server]: {}", msg);
        ctx.writeAndFlush("TCP Server had got msg, index = " + count.incrementAndGet());
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelRegistered -> Channel 注册到它的 EventLoop（即它的生命周期开始）时触发。");
    }


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelUnregistered -> Channel 从它的 EventLoop 注销并且它的所有资源被释放时触发。");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelActive -> Channel 的连接建立时触发。");
        // ctx.channel().closeFuture().addListener -> Channel 关闭时触发。
        ctx.channel().closeFuture().addListener(future -> log.info("[Server]channel close."));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelInactive -> Channel 的连接关闭时触发。");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("[Server]channelRead -> Channel 读取数据时触发");
        // 当消息被传递给 channelRead0 方法时，SimpleChannelInboundHandler 会负责自动释放处理完的消息对象，这减轻了用户的负担，因为不再需要手动释放消息。
        super.channelRead(ctx, msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelReadComplete -> Channel 读取数据完成时触发");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        log.info("[Server]userEventTriggered -> Channel 处理器的生命周期中发生异常时触发");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        log.info("[Server]channelWritabilityChanged -> Channel 可写性改变时触发");
    }

    @Override
    @SuppressWarnings("deprecation")
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        log.info("[Server]exceptionCaught -> Channel 处理器的生命周期中发生异常时触发");
        log.error(cause.toString(), cause);
        ctx.close();
    }

}
